#include "hw_ints.h"
#include "hw_memmap.h"
#include "hw_types.h"
#include "debug.h"
#include "sysctl.h"
#include "interrupt.h"
#include "gpio.h"
#include "pwm.h"
#include "adc.h"
#include "driver_prog.h"


//*****************************************************************************
//	This function is the button interrupt handler. It clears the current 
//interrupt status and start the led.
//*****************************************************************************
void buttonIntHandler(void)
{
	//
	//Clear the current interrupt status
	//
	GPIOPinIntClear(GPIO_PORTC_BASE, GPIO_PIN_4);
	//
	//Start the led
	//
	GPIOPinWrite(GPIO_PORTC_BASE, GPIO_PIN_5, GPIO_PIN_5);	
}

//*****************************************************************************
//	Function used to start the LED or/and button on the kit.
//Checking if any of the LED or the button is configured. Enabling the 
//system peripheral and configuring the LED and/or button.
//*****************************************************************************
void LedAndButtonDriver(struct LB LBconfig)
{
	//
   	//Check if the button and/or the led are configured.
	//
	if((LBconfig.led_and_button[0] | LBconfig.led_and_button[1]) == 1){
		//
   		//Enable the peripherals used by this example.
		//
		SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);
		//
		//Check if the led are configured.
		//
		if(LBconfig.led_and_button[0] == 1){
			//
			//Configure the led using the settings hold by the structure
			//
			GPIOPadConfigSet(GPIO_PORTC_BASE, GPIO_PIN_5,  LBconfig.led_curent, LBconfig.led_PUSH_PULL);
			GPIOPinTypeGPIOOutput(GPIO_PORTC_BASE, GPIO_PIN_5);
		}
	   //
	   //Check if the button are configured.
	   //
		if(LBconfig.led_and_button[1] == 1){
			GPIOPinTypeGPIOInput(GPIO_PORTC_BASE, GPIO_PIN_4);
			if(LBconfig.int_det_mech!=0){
				//
				//Register an iterrupt handler
				//
				GPIOIntTypeSet(GPIO_PORTC_BASE, GPIO_PIN_4, LBconfig.int_det_mech);
				//
				//Enable the interrupts from button
				//
				IntEnable(INT_GPIOC);
				GPIOPinIntEnable(GPIO_PORTC_BASE, GPIO_PIN_4);
			} 
		}
	}	
}
//*****************************************************************************
//	This functions are the interrupt handlers for each PWM generator.
//They clear the current interrupt status
//*****************************************************************************
void PWM0IntHandler(struct PWM_parameters *PWM )
{
	PWMGenIntClear(PWM_BASE,PWM_GEN_0,PWM[0].ulIntTrig);
	GPIOPinWrite(GPIO_PORTC_BASE, GPIO_PIN_5, GPIO_PIN_5);
}

void PWM1IntHandler(struct PWM_parameters *PWM)
{
	PWMGenIntClear(PWM_BASE,PWM_GEN_1,PWM[1].ulIntTrig);
	GPIOPinWrite(GPIO_PORTC_BASE, GPIO_PIN_5, GPIO_PIN_5);
}

void PWM2IntHandler(struct PWM_parameters *PWM)
{
	PWMGenIntClear(PWM_BASE,PWM_GEN_2,PWM[2].ulIntTrig);
	GPIOPinWrite(GPIO_PORTC_BASE, GPIO_PIN_5, GPIO_PIN_5);
}
//*****************************************************************************
//	Function used to start the PWM.
//Checking if the first of the PWMs is configured. Enabling the corresponding 
//system peripheral and configuring the rest of the PWM. Enabling the PWM 
//generator. Continuing with the second PWM.
//*****************************************************************************
void PWM_driver(struct PWM_parameters * PWM ){
	short c;
	for(c=0;c<3;++c)
	{
		if(PWM[c].check==1)
		{
		//
		//Enable the peripherals used by this example.
		//
			SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM);
			if(c==0)
			{
				SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
				GPIOPinTypePWM(GPIO_PORTD_BASE, GPIO_PIN_0 | GPIO_PIN_1);
				PWMGenConfigure(PWM_BASE,PWM_GEN_0,PWM[c].config);
				//
				// Set the PWM period.
				//
				PWMGenPeriodSet(PWM_BASE,PWM_GEN_0,PWM[c].period);
				//
				// Set PWM0 to a duty cycle and PWM1.
				//
				PWMPulseWidthSet(PWM_BASE,	PWM_OUT_0,PWM[c].pulsewidth[0]);
				if(PWM[c].deadBand!=0)
				{
		    		PWMPulseWidthSet(PWM_BASE, PWM_OUT_1,PWM[c].pulsewidth[1]);
				}
			}
			if(c==1)
			{
				SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
				GPIOPinTypePWM(GPIO_PORTB_BASE, GPIO_PIN_0 | GPIO_PIN_1);
				PWMGenConfigure(PWM_BASE,PWM_GEN_1,PWM[c].config);
				//
				// Set the PWM period.
				//
				PWMGenPeriodSet(PWM_BASE,PWM_GEN_1,PWM[c].period);
				//
				// Set PWM0 to a duty cycle and PWM1.
				//
				PWMPulseWidthSet(PWM_BASE,	PWM_OUT_2,PWM[c].pulsewidth[0]);
				if(PWM[c].deadBand!=0)
				{
		    		PWMPulseWidthSet(PWM_BASE, PWM_OUT_3,PWM[c].pulsewidth[1]);
				}
			}
			if(c==2)
			{
				SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
				GPIOPinTypePWM(GPIO_PORTE_BASE, GPIO_PIN_0 | GPIO_PIN_1);
				PWMGenConfigure(PWM_BASE,PWM_GEN_2,PWM[c].config);
				//
				// Set the PWM period.
				//
				PWMGenPeriodSet(PWM_BASE,PWM_GEN_2,PWM[c].period);
				//
				// Set PWM0 to a duty cycle and PWM1.
				//
				PWMPulseWidthSet(PWM_BASE,	PWM_OUT_4,PWM[c].pulsewidth[0]);
				if(PWM[c].deadBand!=0)
				{
		    		PWMPulseWidthSet(PWM_BASE, PWM_OUT_5,PWM[c].pulsewidth[1]);
				}
			}
			//
			// Enable the PWM0 and PWM1 output signals.
			//
			PWMOutputState(PWM_BASE, PWM[c].outputbitA |PWM[c].outputbitB, true);
			//
			// Enable the PWM generator.
			//
			PWMGenEnable(PWM_BASE,PWM[c].genNum );
			//
			//Enable dead band if PWM[c].deadBand!=0
			//
			if(PWM[c].deadBand!=0)
			{
				PWMDeadBandEnable(PWM_BASE,PWM[c].genNum,PWM[c].rise,PWM[c].fall);
			}
			//
			//Interrupt enable if PWM[c].interrupt!=0
			//
			if(PWM[c].interrupt!=0)
			{
				IntEnable(PWM[c].genNum);
				PWMIntEnable(PWM_BASE,PWM[c].ulGenFault);
				PWMGenIntTrigEnable(PWM_BASE,PWM[c].genNum,PWM[c].ulIntTrig);
			}
			//
			//Invert the 1-st output signal if PWM[c].invert[0]!=0
			//
			if(PWM[c].invert[0]!=0)
			{
				PWMOutputInvert(PWM_BASE,PWM_OUT_0_BIT,true);
			}
			//
			//Invert the 2-nd output signal	if PWM[c].inversiq_2!=0
			//
			if(PWM[c].invert[1]!=0)
			{
				PWMOutputInvert(PWM_BASE,PWM_OUT_1_BIT,true);
			}
			//
			//Enable fault interrupt if PWM[c].faultinterrupt!=0
			//
			if(PWM[c].faultinterrupt!=0)
			{
				PWMIntEnable(PWM_BASE,PWM_INT_FAULT);
				//
				//Determens the conditions of the outputs when fault condition occurs
				//
				if(PWM[c].output[0]==0)PWMOutputFault(PWM_BASE,PWM[c].outputbitA,false);
				if(PWM[c].output[0]==1)PWMOutputFault(PWM_BASE,PWM[c].outputbitA,true);
				if(PWM[c].output[1]==0)PWMOutputFault(PWM_BASE,PWM[c].outputbitB,false);
				if(PWM[c].output[1]==1)PWMOutputFault(PWM_BASE,PWM[c].outputbitB,true);
			}
		}
	}
}
//*****************************************************************************
//	Function used to start the ADC.
//Checking if the first ADC is configured. Enabling the corresponding system
//peripheral. Disabling the ADC(in case it is started) and continuing with the
//rest of the ADC configuration. Enabling the ADC.
//*****************************************************************************
void ADC_driver(struct ADC_parameters *ADC)
{
    short c;
	for(c=0;c<4;++c)
	{
		if(ADC[c].check==1)
		{
			SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC);
			//
			// Disables the current Sample Sequencer for configuration
			//
			ADCSequenceDisable(ADC_BASE, c);
			//
			// Set the ADC trigger and priority.
			//
			ADCSequenceConfigure(ADC_BASE, c, ADC[c].ulTrigger, ADC[c].ulPriority);
			//
			// Set ADC Sample Sequencer step.
			//
			ADCSequenceStepConfigure(ADC_BASE, c, ADC[c].ulStep, ADC[c].ulStepConfig);
			//
			// Enables the current Sample Sequencer
			//
			ADCSequenceEnable(ADC_BASE, c);
		}
	}
}
